<DOCTYPE html>
  <html lang="en">

  <head charset="UTF-8">
    <title></title>
  </head>

  <body>
    <script>
      function HashTable() {
        //哈希表以数组形式建立,初始元素放置上限为7
        let array = [];
        let count = 0;
        let limit = 7;

        //封装一个获取字符串转化为字符编码后所放在该哈希表数组下标值的函数
        HashTable.prototype.hashFunc = str => {
          let code = 0
          for (let i = 0; i < str.length; i++) {
            code += 37 * i + str.charCodeAt(i)
          }
          let index = code % this.limit
          return index
        }

        //1.添加/修改方法
        HashTable.prototype.put = (key, value) => {
          //获取下标值
          let index = this.hashFunc(key);
          //判断该下标值在表中是否存在,不存在则新建该编号并添加
          if (this.array[index] == null) {
            this.array[index] = []
            this.array[index].push([key, value]);
            this.count++;
            //元素数量若有变化,就判断是否满足扩容或减容条件,以下一样
            this.isResize()
            return
          }
          //若存在该下标值的数组,判断该数组是否有该元素
          for (let i = 0; i < this.array[index].length; i++) {
            //有则修改
            if (key == this.array[index][i][0]) {
              this.array[index][i][1] = value
              return
            }
          }
          //无则添加
          this.array[index].push([key, value])
          this.count++;
          this.isResize()
        }

        //2.删除方法
        HashTable.prototype.remove = key => {
          let index = this.hashFunc(key);
          if (this.array[index] == null) {
            return null
          }
          for (let i = 0; i < this.array[index].length; i++) {
            if (key == this.array[index][i][0]) {
              delete this.array[index][i]
              this.count--;
              this.isResize()
              return true
            }
          }
          return null
        }

        //3.获取值方法
        HashTable.prototype.get = key => {
          let index = this.hashFunc(key);
          if (this.array[index] == null) {
            return null
          }
          for (let i = 0; i < this.array[index].length; i++) {
            if (key == this.array[index][i][0]) {
              return this.array[index][i][1]
            }
          }
          return null
        }

        //4.判断是否为空
        HashTable.prototype.isEmpty = () => {
          return this.count == 0
        }

        //5.获取元素数量
        HashTable.prototype.size = () => {
          return this.count
        }

        //6.展示哈希表所有key
        HashTable.prototype.show = () => {
          if (this.count > 1) {
            let result = '';
            for (let i = 0; i < this.array.length; i++) {
              if (this.array[i] != null) {
                for (let j = 0; i < this.array[i].length; j++) {
                  result += this.array[i][j][0] + ' '
                }
              }
            }
            return result
          }
          return null
        }

        //7.重置哈希表
        HashTable.prototype.clear = () => {
          this.array = [];
          this.count = 0;
          this.limit = 7;
        }

        //判断是否为质数,辅助获取质数而封装的函数
        HashTable.prototype.isPrime = num => {
          for (let i = 2; i <= Math.floor(Math.sqrt(num)); i++) {
            if (num % i == 0) {
              return false
            }
          }
          return true
        }

        //判断是否扩容或减容
        HashTable.prototype.isResize = () => {
          if (this.count > this.limit * 0.75) {
            let num = this.limit * 2
            this.limit = this.findPrime(num)
            this.resize();
          }
          if (this.limit > 7 && this.count < this.limit * 0.25) {
            let num = this.limit / 2
            this.limit = this.findPrime(num)
            this.resize();
          }
        }

        //获取该数附近的质数
        HashTable.prototype.findPrime = num => {
          while (!isPrime(++num)) { };
          return num
        }

        //扩容/减容刷新哈希表
        HashTable.prototype.resize = () => {
          let newArray = new HashTable();
          newArray.limit = this.limit;
          for (let i = 0; i < this.array.length; i++) {
            if (this.array[i] != null) {
              for (let j = 0; j < this.array[i].length; j++) {
                newArray.put(this.array[i][0], this.array[i][1])
              }
            }
          }
          this.array = newArray.array;
        }
      }
    </script>
  </body>

  </html>